package com.gitee.fanx.rpc;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author fanhang
 */
public class RpcCodec {
	public static final JsonMapper JSON_MAPPER = JsonMapper.builder().serializationInclusion(JsonInclude.Include.NON_NULL).build();
	public static final String EXCEPTION_TEMPLATE = "{\"message\": \"%s\", \"detail\": \"%s\"}";

	public static JsonNode readTree(byte[] bytes) throws IOException {
		return JSON_MAPPER.readTree(bytes);
	}

	public static <T> T convert(JsonNode jsonNode, JavaType toJavaType) {
		return JSON_MAPPER.convertValue(jsonNode, toJavaType);
	}

	public static byte[] encode(Object obj) throws IOException {
		return JSON_MAPPER.writeValueAsBytes(obj);
	}

	public static byte[] encodeException(RpcException ex) {
		return EXCEPTION_TEMPLATE.formatted(ex.getMessage(), ex.getDetail()).getBytes(StandardCharsets.UTF_8);
	}

	public static byte[] encodeException(Exception ex) {
		return EXCEPTION_TEMPLATE.formatted("Server Internal Error", ex.getMessage()).getBytes(StandardCharsets.UTF_8);
	}

	public static RpcException readException(byte[] bytes, int statusCode) throws IOException {
		RpcError error = JSON_MAPPER.readValue(bytes, RpcError.class);
		return new RpcException(statusCode, error.getMessage(), error.getDetail());
	}

	public static <T> T decode(String json, JavaType javaType) throws JsonProcessingException {
		return json == null || json.isBlank() ? null : JSON_MAPPER.readValue(json, javaType);
	}
}
